#!/usr/bin/env perl
# Author: csr
# Date: 2015-11-18
# ScriptName: check_io.pl
# Email: chenshaorong@oschina.cn
# Version: v1.0

# use utf8
use strict;
use warnings;

# set output file
our $file_pos = "/tmp/io.txt";
our $fh;
open($fh, '>>', $file_pos) or die "Could not open file $file_pos: $!";

# set pid file
our $pid_file = "/tmp/check_io.pid";
our $pfh;
open($pfh, '>', $pid_file) or die "Could not open file $pid_file: $!";
print $pfh "$$";
close($pfh);

# exit if user!=root(ubuntu iotop command require root)
if ($> != 0){
	print "iotop: Permission denied.(use root)\n";
	exit 1;
}

print $fh "$^O Perl version: $]\n";

# flag pid used, and set max_hash_len
our %hash;
our $hash_len = 500;

# set query every n seconds
our $sleep_time = 1;

# trap INT(kill -2 or ctrl+c)
sub handler{
    close $fh;
    exit(0);
}
$SIG{'INT'} = 'handler';

while(1){
    if(scalar keys %hash >= $hash_len){
        %hash = {}; 
    }

    my @io_res = `iotop -b -n 1 | sed '1,2d'`;
    foreach(@io_res){
        if(/(\d+)\s+        # Capture TID
            \S+\s+          # PRIO
            \S+\s+          # USER
            (\S+)\s+        # Capture DISK(read)
            (\S+)\s+        # Capture READ
            (\S+)\s+        # Capture DISK(write)
            (\S+)\s+        # Capture WRITE
            \S+\s+.\s+      # SWAPIN
            \S+\s+.\s+      # IO
            (.*)            # COMMAND
            /x){
            if(($3 eq "M/s" && $2 >= 50) || ($5 eq "M/s" && $4 >= 50)){
                my $pid = $1;
                if(exists($hash{$pid}) && ($hash{$pid} == 1)){
                    next;
                }
                $hash{$pid} = 1;
                while(($pid != 1) && ($pid !=0)){
                    my $flag = 0; # flag find ppid
                    my @ps_res = `ps -ef`;
                    foreach(@ps_res){
                        if(/\S+\s+        # UID
                            (\d+)\s+      # Capture PID
                            (\d+)\s+      # Capture PPID
                            \S+\s+        # C
                            \S+\s+        # STIME
                            \S+\s+        # TTY
                            \S+\s+        # TIME
                            (.*)          # Capture CMD
                            /x){
                            if($pid == $1){
                                print $fh "{$pid:$3}";
                                $pid = $2;
                                $flag = 1;
                            }
                        }
                    }
                    if($flag == 0){
                        last;
                    }
                }
                print $fh "\n";
            }
        }
    }
    sleep($sleep_time);
}
